package own.stu.jobgib.playown.util.beanCopy;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class AbstractObject {

    /**
     * 浅克隆
     *
     * @param clazz 目标对象的class
     * @param <T>   目标对象泛型
     * @return 目标对象
     * @throws Exception 异常
     */
    public <T> T clone(Class<T> clazz) throws Exception {
        T target = clazz.newInstance();
        return clone(target);
    }

    /**
     * 浅克隆
     *
     * @param target 目标对象
     * @param <T>    目标对象泛型
     * @return 目标对象
     */
    public <T> T clone(T target) throws Exception {
        BeanCopyUtil.copyProperties(this, target);
        return target;
    }

    public <T> T clone(Class<T> clazz, Integer cloneDirection) throws Exception {
        // 先完成基本字段的浅克隆
        T target = clazz.newInstance();

        // 完成所有List类型的深度克隆
        Class<? extends AbstractObject> thisClass = this.getClass();

        Field[] declaredFields = thisClass.getDeclaredFields();
        for(Field field : declaredFields){
            field.setAccessible(true);

            // 如果判断某个字段是List类型的
            if(field.getType() != List.class){
                continue;
            }

            // 获取List集合中的泛型类型
            Class<?> listGenericClazz = getListGenericType(field);

            // 获取要克隆的目标类型
            // 假设CloneDirection是反向

            Class<?> cloneTargetClazz = getCloneTargetClazz(listGenericClazz, cloneDirection);

            // 将list集合克隆到目标list集合中去
            List clonedList = new ArrayList();
        }

        return target;
    }

    private Class<?> getCloneTargetClazz(Class<?> listGenericClazz, Integer cloneDirection) throws Exception {
        String cloneTargetClassName = null;

        String className = listGenericClazz.getName();

        if (cloneDirection.equals(CloneDirection.FORWARD)) {
            if (className.endsWith(DomainType.VO)) {
                cloneTargetClassName = className.substring(0, className.length() - 2) + "DTO";
            } else if (className.endsWith(DomainType.DTO)) {
                cloneTargetClassName = className.substring(0, className.length() - 3) + "DO";
            }
        }

        if (cloneDirection.equals(CloneDirection.OPPOSITE)) {
            if (className.endsWith(DomainType.DO)) {
                cloneTargetClassName = className.substring(0, className.length() - 2) + "DTO";
            } else if (className.endsWith(DomainType.DTO)) {
                cloneTargetClassName = className.substring(0, className.length() - 3) + "VO";
            }
        }

        return Class.forName(cloneTargetClassName);
    }

    private static Class<?> getListGenericType(Field field) {
        Type genericType = field.getGenericType();
        if(genericType instanceof ParameterizedType){
            ParameterizedType parameterizedType = (ParameterizedType) genericType;
            return (Class<?>) parameterizedType.getActualTypeArguments()[0];
        }
        return null;
    }

    public static void main(String[] args) throws NoSuchFieldException {
        Student student = new Student();
        Field friends = Student.class.getDeclaredField("friends");
        Class<?> listGenericType = getListGenericType(friends);
        System.out.println(listGenericType);
    }

}
